page.tsx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. "use client";
  2. import {
  3. claimActivityReward,
  4. ContinuousCfgItem,
  5. ContinuousListItem,
  6. ContinuousResult,
  7. ContinuousRewardItem,
  8. ContinuousStageItem,
  9. getContinuousRechargeInfo,
  10. } from "@/api/activity";
  11. import CutDown from "@/components/CutDown";
  12. import GlobalNotify from "@/components/ModalPopup/GlobalNotifyModal";
  13. import { useRouter } from "@/i18n/routing";
  14. import { formatAmount } from "@/utils/index";
  15. import { Toast } from "antd-mobile";
  16. import BigNumber from "bignumber.js";
  17. import clsx from "clsx";
  18. import { useTranslations } from "next-intl";
  19. import { useSearchParams } from "next/navigation";
  20. import React from "react";
  21. import styles from "./page.module.scss";
  22. interface Cfg1Item {
  23. text: string;
  24. text2: string;
  25. key: number;
  26. footer: string;
  27. footer2?: string;
  28. }
  29. interface StageItem extends ContinuousStageItem, Cfg1Item {}
  30. interface ListItem {
  31. dayId: number;
  32. data: ContinuousListItem;
  33. }
  34. interface RewardItem {
  35. dayId: number;
  36. data: ContinuousRewardItem[];
  37. }
  38. //"#297fcf"
  39. const DayItem = ({
  40. data,
  41. idx,
  42. onClaim,
  43. level,
  44. }: {
  45. data: ContinuousCfgItem;
  46. idx: number;
  47. onClaim: (data: ContinuousCfgItem) => void;
  48. level: string;
  49. }) => {
  50. const dayColor = React.useMemo(() => {
  51. return ["#12940f", "#297fcf", "#ec3920"][idx % 3];
  52. }, [idx]);
  53. const doClaim = () => {
  54. if (onClaim && typeof onClaim === "function") {
  55. onClaim(data);
  56. }
  57. };
  58. return (
  59. <div className={styles.dayItemBox}>
  60. {data.id >= 2 && (
  61. <div className="mb-[.1rem] flex flex-row justify-center">
  62. <div className={styles.canGet}>Grande Prêmio Disponível</div>
  63. </div>
  64. )}
  65. {!!data.end_at && (
  66. <div className="item-center mb-[.1rem] flex flex-row justify-center">
  67. <CutDown
  68. endTime={data.end_at - Date.now() / 1000}
  69. itemBgColor="rgba(255,255,255,.4)"
  70. ></CutDown>
  71. </div>
  72. )}
  73. <div className={styles.premioItem}>
  74. <div className={styles.premioItemDay}>
  75. <span style={{ color: dayColor }}>{data.days}</span>
  76. </div>
  77. <div className="flex flex-col justify-between">
  78. <div className="text-[.16rem] font-bold">
  79. Recarga contínua por {data.days} dias
  80. </div>
  81. <div className="flrx-row flex items-center justify-between">
  82. <div>
  83. Recompensa de login
  84. {/* {level} */}
  85. {/* {data.target_reward}R */}
  86. </div>
  87. <div
  88. className={clsx(styles.premioItemBtn, {
  89. [styles.disabled]: !data.isCanClaim,
  90. })}
  91. onClick={doClaim}
  92. >
  93. {data.is_sign === 0 ? "Recebido" : "Receber"}
  94. </div>
  95. </div>
  96. </div>
  97. </div>
  98. </div>
  99. );
  100. };
  101. const Page = () => {
  102. const t = useTranslations();
  103. const query = Object.fromEntries(useSearchParams());
  104. const [data, setData] = React.useState<ContinuousResult>({} as ContinuousResult);
  105. const router = useRouter();
  106. const dayContainer = React.useRef<HTMLDivElement>(null);
  107. const [amount, setAmount] = React.useState<any>({});
  108. const [visible, setVisible] = React.useState<boolean>(false);
  109. const act = React.useMemo(() => {
  110. if (!data || data.type === 11) return 0;
  111. return 1;
  112. }, [data]);
  113. React.useEffect(() => {
  114. getData();
  115. // eslint-disable-next-line react-hooks/exhaustive-deps
  116. }, []);
  117. const getData = async () => {
  118. const res = await getContinuousRechargeInfo({ activity_id: Number(query.activity_id) });
  119. if (res.code === 200) {
  120. setData(res.data);
  121. }
  122. };
  123. const cfg1: Record<number, Cfg1Item> = React.useMemo(() => {
  124. return {
  125. 1: {
  126. text: "LOGIN ",
  127. text2: "PLATINUM",
  128. key: 1,
  129. footer: "Alcançou",
  130. },
  131. 2: {
  132. text: "LOGIN",
  133. text2: "GOLD",
  134. key: 2,
  135. footer: "Ainda preciso",
  136. },
  137. 3: {
  138. text: "LOGIN",
  139. text2: "DIAMANTE",
  140. key: 3,
  141. footer: "Ainda preciso",
  142. },
  143. // 4: {
  144. // text: "ENTRAR NO",
  145. // text2: "MONOPOLY",
  146. // key: 4,
  147. // footer: "Ainda preciso",
  148. // },
  149. // 5: {
  150. // text: "ENTRAR NO",
  151. // text2: "MONOPOLY",
  152. // key: 5,
  153. // footer: "Ainda preciso",
  154. // },
  155. // 6: {
  156. // text: "ENTRAR NO",
  157. // text2: "MONOPOLY",
  158. // key: 6,
  159. // footer: "Ainda preciso",
  160. // },
  161. // 7: {
  162. // text: "ENTRAR NO",
  163. // text2: "MONOPOLY",
  164. // key: 7,
  165. // footer: "Ainda preciso",
  166. // },
  167. };
  168. }, []);
  169. const stage = React.useMemo<StageItem[]>(() => {
  170. let stags = data?.list?.stage;
  171. if (!data?.list?.stage) {
  172. stags = [
  173. { id: 1 },
  174. { id: 2 },
  175. { id: 3 },
  176. // { id: 4 },
  177. // { id: 5 },
  178. // { id: 6 },
  179. // { id: 7 },
  180. ] as unknown as ContinuousStageItem[];
  181. }
  182. const result: StageItem[] = stags
  183. .map((item) => {
  184. console.log(112233, item);
  185. return {
  186. ...item,
  187. ...cfg1[item.id],
  188. footer2: item.diff_num ? `${item.diff_num}R` : "",
  189. };
  190. })
  191. .sort((a: ContinuousStageItem, b: ContinuousStageItem) => a.id - b.id);
  192. return result; //[{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }];
  193. }, [data?.list?.stage, cfg1]);
  194. const list = React.useMemo<ListItem[]>(() => {
  195. if (!data?.list?.list) {
  196. return [];
  197. }
  198. const result: ListItem[] = [] as ListItem[];
  199. Object.keys(data?.list?.list).forEach((key: string) => {
  200. const item = data?.list?.list[key as any];
  201. const key1 = Object.keys(item)[0];
  202. result.push({ dayId: Number(key), data: item[key1 as any] });
  203. });
  204. console.log(result);
  205. return result.sort((a, b) => a.dayId - b.dayId);
  206. }, [data?.list?.list]);
  207. const reward_list = React.useMemo<RewardItem[]>(() => {
  208. if (!data?.list?.reward_list) {
  209. return [];
  210. }
  211. const result: RewardItem[] = [] as RewardItem[];
  212. Object.keys(data?.list?.reward_list).forEach((key: string) => {
  213. const item = data?.list?.reward_list[key as any];
  214. const res2: ContinuousRewardItem[] = [];
  215. Object.keys(item).forEach((key2: string) => {
  216. const item2 = item[key2 as any];
  217. res2.push(item2);
  218. });
  219. result.push({ dayId: Number(key), data: res2 });
  220. });
  221. return result;
  222. }, [data?.list?.reward_list]);
  223. const waitList = React.useMemo<ContinuousCfgItem[]>(() => {
  224. if (!data?.list?.config_list) return [];
  225. const result = [] as ContinuousCfgItem[];
  226. data?.list?.config_list.forEach((item) => {
  227. if (
  228. item.is_sign === 0 ||
  229. item.is_suss === 1 ||
  230. !(item.start_at * 1000 < Date.now() && item.end_at * 1000 > Date.now())
  231. ) {
  232. item.isCanClaim = false;
  233. } else {
  234. item.isCanClaim = true;
  235. }
  236. result.push(item);
  237. });
  238. return result.sort((a, b) => a.days - b.days);
  239. }, [data?.list?.config_list]);
  240. const goDeposit = () => {
  241. router.push("/deposit");
  242. };
  243. const doClaim = async (data: ContinuousCfgItem) => {
  244. if (!query.activity_id) {
  245. Toast.show({ content: "Missing activity ID" });
  246. return;
  247. }
  248. if (!data.is_sign) return;
  249. try {
  250. const res = await claimActivityReward({
  251. activity_id: Number(query.activity_id),
  252. id: data.days,
  253. });
  254. if (res.code === 200 && res?.data?.code === 1) {
  255. const amountObj: any = {};
  256. if (res?.data?.reward) {
  257. res?.data?.reward.forEach((item: any) => {
  258. amountObj[`coin_${item.coin_type}`] = formatAmount(item.amount);
  259. });
  260. }
  261. if (res?.data?.extra_reward) {
  262. res?.data?.extra_reward.forEach((item: any) => {
  263. amountObj[`coin_${item.coin_type}`] = formatAmount(
  264. new BigNumber(amountObj[`coin_${item.coin_type}`] || 0)
  265. .plus(item.amount)
  266. .toString()
  267. );
  268. });
  269. }
  270. setAmount(amountObj);
  271. setVisible(true);
  272. getData();
  273. } else {
  274. throw new Error(t(`code.400`));
  275. }
  276. } catch (error: any) {
  277. if (error) {
  278. Toast.show({
  279. content: error.message || error.toString(),
  280. maskClickable: false,
  281. });
  282. }
  283. }
  284. };
  285. return (
  286. <div className={clsx(styles.continuePage)}>
  287. <div className={styles.container}>
  288. <div className={styles.top}>
  289. <img className={styles.img} src="/proxyRecharge/top.png" alt="" />
  290. {/* <div className={styles.recharge} onClick={goDeposit}>
  291. RECARGA
  292. </div> */}
  293. </div>
  294. <div className={styles.content}>
  295. <div className={styles.tip}>
  296. <div
  297. className={clsx(styles.text, {
  298. [styles.active]: act === 0,
  299. })}
  300. >
  301. Meu login
  302. </div>
  303. <div
  304. className={clsx(styles.text, {
  305. [styles.active]: act === 1,
  306. })}
  307. >
  308. Login de amigo
  309. </div>
  310. </div>
  311. <div className={styles.inner}>
  312. <div
  313. className={clsx(styles.innerContainer, {
  314. [styles.innerContainer1]: act === 1,
  315. })}
  316. >
  317. {!!list?.length && (
  318. <div
  319. className={clsx(styles.stageBox, {
  320. [styles.stageBox1]: act === 1,
  321. })}
  322. >
  323. {list.map((item, idx) => {
  324. return (
  325. <div
  326. key={item.dayId}
  327. className={clsx(styles.stageItem, {
  328. [styles.unlock]: item.data.is_sign === 1,
  329. [styles.lock]: item.data.is_sign === 0,
  330. })}
  331. >
  332. <div className={styles.stageText}>
  333. <div>Para ser</div>
  334. <div className="mt-[.03rem]">concluído</div>
  335. </div>
  336. <div className={styles.stageText2}>
  337. <span>recarga</span>
  338. <div className={styles.stageText2Num}>
  339. {item.data.pay_num}
  340. </div>
  341. </div>
  342. <div className={clsx(styles.stageImg)}></div>
  343. <div className={styles.stageDay}>
  344. Dia {item.dayId}
  345. </div>
  346. </div>
  347. );
  348. })}
  349. </div>
  350. )}
  351. {/* {!!list?.length && (
  352. <div className={styles.daybox}>
  353. <div className={styles.dayContainer} ref={dayContainer}>
  354. {list.map((item: any) => {
  355. return (
  356. <div
  357. key={item.dayId}
  358. className={clsx(styles.dayItem, {
  359. [styles.active]: item.data.is_sign,
  360. })}
  361. >
  362. <div className={styles.dayItemText}>
  363. {item.dayId} dia
  364. </div>
  365. <div className={styles.dayitemTextActive}>
  366. <img
  367. src={`/continuous/s${item.data.id}.png`}
  368. alt=""
  369. />
  370. <div className="flex flex-row items-end text-[#dbc6ff]">
  371. <span className="relative top-[1px] mt-[2px] text-[.13rem]">
  372. {item.dayId}
  373. </span>
  374. <span>dia</span>
  375. </div>
  376. <div>recarga</div>
  377. <div className="mt-[.03rem] w-[100%] overflow-hidden text-ellipsis text-[#ffb400]">
  378. {item?.data?.pay_num}
  379. </div>
  380. </div>
  381. </div>
  382. );
  383. })}
  384. </div>
  385. </div>
  386. )} */}
  387. {!!waitList.length && (
  388. <div className={styles.premio}>
  389. <div
  390. className={clsx(styles.premioTitle, {
  391. [styles.premioTitle1]: act === 1,
  392. })}
  393. >
  394. {act === 1 && (
  395. <div className={styles.premioTitleText}>
  396. <div>AMIGO ENTRAR PARA</div>
  397. <div>RECEBER CORTESIA</div>
  398. </div>
  399. )}
  400. {act === 0 && (
  401. <div className={styles.premioTitleText}>
  402. <div>ENTRAR E RECEBER CORTESIA</div>
  403. </div>
  404. )}
  405. </div>
  406. <div className={styles.premioContainer}>
  407. <div className={styles.premioContent}>
  408. {waitList.map((item, idx: number) => {
  409. return (
  410. <DayItem
  411. key={item.days}
  412. data={item}
  413. idx={idx}
  414. onClaim={doClaim}
  415. level={cfg1[item.id].text2}
  416. ></DayItem>
  417. );
  418. })}
  419. </div>
  420. </div>
  421. </div>
  422. )}
  423. <div className={styles.cfgbox}>
  424. <div className={styles.cfgContainer} ref={dayContainer}>
  425. <div className={styles.cfgHeader}>
  426. <div>
  427. Dias de
  428. <br />
  429. depósito
  430. </div>
  431. <div>
  432. Requisitos da <br />
  433. atividade
  434. </div>
  435. {data.type === 11 && (
  436. <div>
  437. Valor do
  438. <br />
  439. bônus
  440. </div>
  441. )}
  442. {data.type === 13 && (
  443. <div>
  444. Recompensas <br />
  445. de Agente
  446. </div>
  447. )}
  448. </div>
  449. {reward_list.map((item) => {
  450. return (
  451. <div key={item.dayId} className={styles.cfgItem}>
  452. <div className={styles.cfgItemName}>
  453. Recarga contínua por{" "}
  454. <div className="text-[#faab00]">
  455. {item.dayId}dias
  456. </div>
  457. </div>
  458. <div className="flex-1">
  459. {item.data.map((item2, idx) => {
  460. return (
  461. <div
  462. key={item2.id}
  463. className={styles.cfgItemChild}
  464. >
  465. <div>
  466. Mais de {item2.target_num} por
  467. dia
  468. </div>
  469. <div>{item2.target_reward}</div>
  470. </div>
  471. );
  472. })}
  473. </div>
  474. </div>
  475. );
  476. })}
  477. </div>
  478. </div>
  479. <div className={styles.introbox}>
  480. <div className={styles.introContainer}>
  481. <div className={styles.introTitle}>
  482. <span className={styles.introTitleText}>
  483. Regras de Atividade
  484. </span>
  485. </div>
  486. <div className="h-[.2rem]"></div>
  487. <ul className={styles.introboxDesc}>
  488. <li>
  489. Jogadores que atendem aos requisitos podem receber o
  490. bônus diretamente.
  491. </li>
  492. <li>
  493. Solicite o bônus desta promoção dentro do período
  494. promocional. Não se inscrever após o prazo limite será
  495. considerado como desistência automática.
  496. </li>
  497. <li>
  498. Ao participar desta promoção, você concorda em cumprir
  499. as Regras e Termos da Promoção.
  500. </li>
  501. </ul>
  502. <div className="mt-[.1rem]">
  503. <div className="pb-[.1rem] text-center text-[.14rem] font-bold">
  504. Termos e Condições
  505. </div>
  506. </div>
  507. <ul className={styles.introboxDesc}>
  508. <li>
  509. Todas as ofertas são liquidadas em RMB (CNY) e são
  510. baseadas no horário de Pequim.
  511. </li>
  512. <li>
  513. Cada jogador, domicílio, endereço, endereço de e-mail,
  514. número de telefone, método de pagamento (mesmo cartão de
  515. débito/crédito/conta bancária) e endereço IP só pode
  516. aproveitar a oferta uma vez por dia.
  517. </li>
  518. <li>
  519. Se for descoberto que qualquer grupo ou indivíduo está
  520. obtendo bônus desonestamente ou abusando de benefícios
  521. da empresa, a empresa reserva-se o direito de congelar
  522. ou cancelar o saldo do grupo.
  523. </li>
  524. <li>
  525. A Ginkgo Live reserva-se o direito de interpretação
  526. final do evento; bem como o direito de modificar ou
  527. encerrar o evento sem aviso prévio.
  528. </li>
  529. </ul>
  530. </div>
  531. </div>
  532. </div>
  533. </div>
  534. </div>
  535. </div>
  536. <GlobalNotify
  537. amount={amount}
  538. visible={visible}
  539. onChange={() => setVisible(false)}
  540. deraction={5000}
  541. ></GlobalNotify>
  542. </div>
  543. );
  544. };
  545. export default Page;